<script setup lang="ts">
import { type PropType, ref, type VNode } from "vue";
import { message } from "ant-design-vue";

defineOptions({ name: "pending-button" });
const props = defineProps({
  fn: { type: Function, required: true },
  fnArgs: { type: [String, Number, Boolean, Object, Array] as PropType<any> },
  type: { type: String as PropType<"default" | "primary" | "text" | "dashed" | "link" | "ghost"> },
  size: { type: String as PropType<"large" | "middle" | "small"> },
  shape: { type: String as PropType<"default" | "circle" | "round"> },
  icon: { type: Object as PropType<VNode> },
  htmlType: { type: String },
  disabled: { type: Boolean, default: () => undefined },
  block: { type: Boolean, default: () => undefined },
  danger: { type: Boolean, default: () => undefined },
  prevent: { type: Boolean, default: () => undefined },
  stop: { type: Boolean, default: () => undefined },
  pendingText: { type: String },
  showErrorMessage: { type: Boolean },
  disableMode: { type: Boolean },
});

const pending = ref(false);
const onClick = async (e: PointerEvent) => {
  pending.value = true;
  try {
    if (props.prevent) e.preventDefault();
    if (props.stop) e.stopPropagation();
    if (Array.isArray(props.fnArgs)) {
      await props.fn!(...props.fnArgs, e);
    } else {
      await props.fn!(props.fnArgs, e);
    }
  } catch (e: any) {
    console.error(e);
    if (props.showErrorMessage) message.error(e.message);
  } finally {
    pending.value = false;
  }
};
</script>

<template>
  <a-button
    :type="type"
    :size="size"
    :danger="danger"
    :icon="icon"
    :shape="shape"
    :html-type="htmlType"
    :loading="!disableMode && pending"
    :disabled="disabled || (disableMode && pending)"
    @click="onClick"
  >
    <template v-if="pending && pendingText">{{ pendingText }}</template>
    <slot v-else />
  </a-button>
</template>
